﻿using AutoMapper;
using DFGK.IRepository;
using DFGK.IService;
using DFGK_WMS.Common;
using DFGK_WMS.Model.Dto;
using DFGK_WMS.Model.Enum;
using DFGK_WMS.Model.Models;
using DFGK_WMS.Model.Wcs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;

namespace DFGK.Service
{
    public class InstructService : BaseService, IInstructService
    {
        private readonly IReceivingOrderDetailRepository _receivingOrderDetailRepository;
        private readonly IReceivingBillDetailRepository _receivingBillDetailRepository;
        private readonly IPutawayOrderDetailRepository _putawayOrderDetailRepository;
        private readonly IShippingLockCellRepository _shippingLockCellRepository;
        private readonly IShippingOrderDetailRepository shippingOrderDetailRepository;
        private readonly IStackingStorageRepository _stackingStorageRepository;
        private readonly IInventoryDetailRepository _inventoryDetailRepository;
        private readonly IReceivingBillRepository _receivingBillRepository;
        private readonly IPutawayOrderRepository _putawayOrderRepository;
        private readonly IInventoryRepository _inventoryRepository;
        private readonly IInstructRepository _instructRepository;
        private readonly IPalletRepository _palletRepository;
        private readonly IPickingOrderRepository _pickingOrderRepository;
        private readonly IPickingOrderDetailRepository _pickingOrderDetailRepository;
        private readonly IAreaRepository _areaRepository;
        private readonly IWarehouseRepository _warehouseRepository;
        private readonly ITransferBinOrderDetailRepository _transferBinOrderDetailRepository;
        private readonly IRoutewayRepository _routewayRepository;
        private readonly IShelfRepository _shelfRepository;
        private readonly ITransferBinOrderRepository _transferBinOrderRepository;
        private readonly WcsHttpClient wcsHttpClient;
        private readonly ICellRepository _cellRepository;
        private readonly IUnitOfWork _unitOfWork;

        public InstructService(IMapper mapper, IInstructRepository _instructRepository, IReceivingOrderDetailRepository receivingOrderDetailRepository, IShippingLockCellRepository shippingLockCellRepository, IShippingOrderDetailRepository shippingOrderDetailRepository, IStackingStorageRepository stackingStorageRepository, IPutawayOrderRepository putawayOrderRepository, IPutawayOrderDetailRepository putawayOrderDetailRepository, IReceivingBillRepository _receivingBillRepository, IReceivingBillDetailRepository _receivingBillDetailRepository, IInventoryRepository _inventoryRepository, IInventoryDetailRepository _inventoryDetailRepository, ICellRepository _cellRepository, IUnitOfWork _unitOfWork, IPalletRepository _palletRepository, IPickingOrderRepository pickingOrderRepository, IPickingOrderDetailRepository pickingOrderDetailRepository, IAreaRepository areaRepository, IWarehouseRepository warehouseRepository, ITransferBinOrderDetailRepository transferBinOrderDetailRepository, IRoutewayRepository routewayRepository, IShelfRepository shelfRepository, ITransferBinOrderRepository transferBinOrderRepository, WcsHttpClient wcsHttpClient) : base(mapper)
        {
            _receivingOrderDetailRepository = receivingOrderDetailRepository;
            _putawayOrderDetailRepository = putawayOrderDetailRepository;
            _shippingLockCellRepository = shippingLockCellRepository;
            this.shippingOrderDetailRepository = shippingOrderDetailRepository;
            _stackingStorageRepository = stackingStorageRepository;
            _putawayOrderRepository = putawayOrderRepository;
            this._receivingBillDetailRepository = _receivingBillDetailRepository;
            this._inventoryDetailRepository = _inventoryDetailRepository;
            this._receivingBillRepository = _receivingBillRepository;     
            this._inventoryRepository = _inventoryRepository;
            this._instructRepository = _instructRepository;
            this._palletRepository = _palletRepository;
            this._pickingOrderRepository = pickingOrderRepository;
            this._pickingOrderDetailRepository = pickingOrderDetailRepository;
            this._areaRepository = areaRepository;
            this._warehouseRepository = warehouseRepository;
            this._transferBinOrderDetailRepository = transferBinOrderDetailRepository;
            this._routewayRepository = routewayRepository;
            this._shelfRepository = shelfRepository;
            this._transferBinOrderRepository = transferBinOrderRepository;
            this.wcsHttpClient = wcsHttpClient;
            this._cellRepository = _cellRepository;
            this._unitOfWork = _unitOfWork;
        }

        public bool CancelInstruct(long id, out string message)
        {
           
            message = "";
            var instructobj = _instructRepository.QueryEntityWhere(i => i.Id == id && i.Status == 2);
            if (instructobj == null)
            {
                message = "找不到该指令！";
                return false;
            }
            bool result = false;
            _unitOfWork.BeginTransaction();
            switch (instructobj.InstructType)
            {
                case 1:
                    result = CancelRevingOrder(instructobj, out message);
                    break;
                case 2:
                case 6:
                    result = CancelTaskOutboundShipments(instructobj.PalletBarcode, out message);
                    break;
                case 3:
                    result = CancelTaskTransferBinOrder(instructobj, out message);
                    break;
            }
            if (result)
            {
                _unitOfWork.CommitChanges();
                return true;
            }

            _unitOfWork.RollbackChanges();
            return false;
        }

        #region 入库-撤销指令
        private bool CancelRevingOrder(Instruct instructobj, out string message)
        {
            message = "";
            //清楚托盘所在位置
            var pobj = _palletRepository.QueryEntityWhere(x => x.PalletBarcode == instructobj.PalletBarcode);
            if (pobj != null)
            {
                pobj.LocationCode = string.Empty;
                pobj.LocationName = string.Empty;
            }
            //删除指令
            _instructRepository.DelEntity(instructobj);
            if(instructobj.RelatedOrderId == null)
            {
                message = "关联的入库单id有误！";
                return false;
            }
            var reveingor = _receivingOrderDetailRepository.QueryEntityById((long)instructobj.RelatedOrderId);
            if (reveingor == null)
            {
                message = "找不到入库单！";
                return false;
            }
            //删除入库单
            _receivingOrderDetailRepository.DelEntity(reveingor);
            if (instructobj.StackingStorageId == null)
            {
                message = "关联的组垛id有误！";
                return false;
            }
            var stackingstorageobj = _stackingStorageRepository.QueryEntityById((long)instructobj.StackingStorageId);
            if (stackingstorageobj != null)
                //删除组垛信息
                _stackingStorageRepository.DelEntity(stackingstorageobj);
           
            //上架单
            var putobj = _putawayOrderRepository.QueryEntityWhere(x => x.RelatedOrderDetailId == reveingor.Id && x.Status == 4);
            if (putobj != null)
            {
                //删除上架单
                _putawayOrderRepository.DelEntity(putobj);
                var putdeobj = _putawayOrderDetailRepository.QueryEntityWhere(x => x.PutawayOrderId == putobj.Id);
                if (putdeobj != null)
                    _putawayOrderDetailRepository.DelEntity(putdeobj);
            }
            else
            {
                message = "找不到上架单信息！";
                return false;
            }
          
            if (reveingor.ReceivingBillId == null)
            {
                message = "关联的收货单id有误！";
                return false;
            }
            //收货单
            var rebvingbillobj = _receivingBillRepository.QueryEntityById((long)reveingor.ReceivingBillId);
            if (rebvingbillobj == null)
            {
                message = "找不到收货单信息！";
                return false;
            }
            //收货单恢复状态和数量
            rebvingbillobj.Status = 0;
            rebvingbillobj.BeginDate = null;
            rebvingbillobj.EndDate = null;
            var rebvingbilldetailsobj = _receivingBillDetailRepository.QueryEntityWhere(x => x.BillId == rebvingbillobj.Id);
            if (rebvingbilldetailsobj == null)
            {
                message = "找不到收货单明细信息！";
                return false;
            }
            rebvingbilldetailsobj.ReceivedQty -= instructobj.Qty;
            //库存
            var invobj = _inventoryRepository.QueryEntityWhere(x => x.RelatedOrderDetailId == reveingor.Id);
            if (invobj == null)
            {
                message = "找不到库存信息！";
                return false;
            }
            _inventoryRepository.DelEntity(invobj);
            //库存明细
            var indvobj = _inventoryDetailRepository.QueryEntityWhere(x => x.InventoryId == invobj.Id);
            if (indvobj != null)
                _inventoryDetailRepository.DelEntity(indvobj);

            //仓位
            var cellobj = _cellRepository.QueryEntityWhere(x => x.Code == invobj.LocationCode);
            if (cellobj != null)
            {
                cellobj.FullStatus = 0;
                cellobj.IsLock = false;
                cellobj.BusinessType = 0;
                cellobj.Status = 1;
                _cellRepository.UpdEntity(cellobj);
            }
            else
            {
                message = "仓位信息有误！";
                return false;
            }
            return _unitOfWork.SaveChangesEntity();
        }
        #endregion


        #region 出库-撤销指令
        private bool CancelTaskOutboundShipments(string pallCode, out string message)
        {
            //取消出库任务是需要判断本次出库任务后面仓位是否有任务，如果有任务就需要将本次取消出库任务变成移库任务不能挡住后面任务
            message = "";
            //bool result = false;
            try
            {
                var pallData = _palletRepository.QueryEntityWhere(p => p.PalletBarcode == pallCode);
                if (pallData == null)
                {
                    message = "未查询到托盘!";
                    return false;
                }

                //根据托盘去查询指令 (一个托盘可能会存在多个指令如果取消则都需要取消)
                var instructList = _instructRepository.GetEntityWhereAll(x => x.PalletBarcode == pallCode && x.Status == 2 && x.InstructType == 2 || (x.PalletBarcode == pallCode && x.Status == 2 && x.InstructType == 6)).ToList();
                if (!instructList.Any())
                {
                    message = "未查询到指令任务!";
                    return false;
                }

                var cellData = _cellRepository.QueryEntityWhere(c => c.Code == pallData.LocationCode);
                if (cellData == null)
                {
                    message = "未查询到仓位!";
                    return false;
                }

                string pickingCode = null;

                foreach (var instruct in instructList)
                {
                    var lockCell = _shippingLockCellRepository.QueryEntityWhere(l => l.Id == instruct.RelatedOrderDetailId && l.Status == 3);
                    if (lockCell == null)
                    {
                        message = "未查询到出库单明细!";
                        return false;
                    }
                    //修改出库单明细状态
                    lockCell.Status = 0;
                    _shippingLockCellRepository.UpdEntity(lockCell);

                    //查询出库单
                    var shippingOrder = shippingOrderDetailRepository.QueryEntityWhere(s => s.Id == instruct.RelatedOrderId && s.Status == 3);
                    if (shippingOrder == null)
                    {
                        message = "未查询到出库单!";
                        return false;
                    }
                    shippingOrder.Status = 0;
                    shippingOrderDetailRepository.UpdEntity(shippingOrder);

                    //将库存数据改成正常
                    var inventory = _inventoryRepository.QueryEntityWhere(x => lockCell.InventoryId == x.Id && x.Status == 4 && x.IsLock == true);
                    if (inventory == null)
                    {
                        message = "未查询到库存数据!";
                        return false;
                    }
                    inventory.IsLock = true; //状态还是锁住的状态
                    inventory.Status = 1;

                   
                    _instructRepository.DelEntity(instruct);

                    var picking = _pickingOrderRepository.QueryEntityWhere(p => p.PalletBarcode == pallCode && p.Status == 4);
                    if (picking == null)
                    {
                        message = "未查询到下架单";
                        return false;
                    }
                    if (!string.IsNullOrEmpty(picking.DescAddress))
                    {
                        pickingCode = picking.Code;
                    }
                    _pickingOrderRepository.DelEntity(picking);

                    var pickingDetail = _pickingOrderDetailRepository.QueryEntityWhere(p => p.OrderId == picking.Id);
                    if (pickingDetail == null)
                    {
                        message = "未查询到下架单明细";
                        return false;
                    }
                    _pickingOrderDetailRepository.DelEntity(pickingDetail);
                    if (!_unitOfWork.SaveChangesEntity())
                    {
                        message = "取消任务失败";
                        return false;
                    }
                }

                if (pickingCode == null)
                {
                    message = "未获取到任务号";
                    return false;
                }
                CancelTaskData cancelTaskData = new CancelTaskData();
                cancelTaskData.MsgTime = DateTime.Now.ToString();
                cancelTaskData.TaskId = pickingCode;
                if (Config.IsDev == false)
                {
                    var newWcsApi = wcsHttpClient.CancelTaskApi(cancelTaskData);
                    if (newWcsApi.returnStatus == 1)
                    {
                        message = "取消任务失败," + newWcsApi.returnInfo;
                        return false;
                    }
                }
                //使用三元表达式，来判断查询条件
                var depthCell = cellData.LineNo > 4 ? _cellRepository.GetEntityWhereAll(c => c.LayerNo == cellData.LayerNo && c.ColumnNo == cellData.ColumnNo && c.LineNo > cellData.LineNo && c.LineNo > 4).OrderBy(c => c.DepthIndex).ToList() : _cellRepository.GetEntityWhereAll(c => c.LayerNo == cellData.LayerNo && c.ColumnNo == cellData.ColumnNo && c.LineNo < cellData.LineNo && c.LineNo < 4).OrderBy(c => c.DepthIndex).ToList();

                #region 判断是否需要把本次任务换成移库任务
                bool WhetherTransferBin = false;
                foreach (var decell in depthCell)
                {
                    //这里还能是移库和出库任务 如果取消任务后面的仓位有任务就将本次取消任务给换成移库
                    var transferBinTaks = _putawayOrderRepository.QueryEntityWhere(p => p.LocationCode == decell.Code && p.Status == 4 && p.SourceType == 3);
                    if (transferBinTaks != null)
                    {
                        WhetherTransferBin = true;
                        break;
                    }
                    //查询是否有出库任务
                    var outTaks = _pickingOrderRepository.QueryEntityWhere(p => p.LocationCode == decell.Code && p.Status == 4 && p.SourceType == 2);
                    if (outTaks != null)
                    {
                        WhetherTransferBin = true;
                        break;
                    }
                }
                if (WhetherTransferBin)
                {
                    //传入的是需要移库的仓位数据而不是出库仓位数据
                    var transCellData = ShippingTransferBinInventory(cellData.LayerNo, cellData.Code, cellData.AreaCode, out message);
                    if (transCellData == null)
                    {
                        message = "创建移库任务失败，" + message;
                        return false;
                    }

                    //查询移库单
                    var putaway = _putawayOrderRepository.QueryEntityWhere(p => p.Status == 4 && p.LocationCode == transCellData.Code && p.SourceType == 3);
                    if (putaway == null)
                    {
                        message = "未查询到移库任务!";
                        return false;
                    }
                    //在将取消的任务下发成移库任务 注意要将优先级提高
                    TaskAccept taskAccept = new TaskAccept
                    {
                        tasks = new List<Tasks>()
                        {
                            new Tasks()
                            {
                                TaskId = putaway.Code,
                                TaskType = 2,
                                BarCode = putaway.PalletBarcode,
                                EndNode = putaway.LocationCode,
                                StartNode = cellData.Code,
                                Order = 1
                            }
                        },
                        Warehouse = Config.WMSWarehouseCode,
                        GroupId = Guid.NewGuid().ToString("N"),
                        MsgTime = DateTime.Now.ToString(),
                        PriorityCode = 80 //优先级80
                    };


                    if (Config.IsDev == false)
                    {
                        //wcs返回结果
                        var Wcsresult = wcsHttpClient.TaskAcceptApi(taskAccept);
                        if (Wcsresult.returnStatus != 0)
                        {
                            message = "下发移库任务失败，" + Wcsresult.returnInfo;
                            return false;
                        }
                    }
                    return true;
                }
                #endregion
                return true;
            }
            catch (Exception ex)
            {
                _unitOfWork.RollbackChanges();
                throw;
            }
        }
        #endregion


        #region 移库-撤销指令
        private bool CancelTaskTransferBinOrder(Instruct instructobj, out string message)
        {
            message = string.Empty;
            string pickingCode = null;
            //查询移库单
            var transobj = _transferBinOrderRepository.QueryEntityWhere(t => t.Id == instructobj.RelatedOrderId && t.Status == 3);
            if (transobj == null)
            {
                message = "未查询到移库单!";
                return false;
            }
            var transDetailobj = _transferBinOrderDetailRepository.QueryEntityWhere(t => t.Id == instructobj.RelatedOrderDetailId && t.Status == 3);
            if (transDetailobj == null)
            {
                message = "未查询到移库单明细!";
                return false;
            }
            transobj.Status = 0;
            transDetailobj.Status = 0;
            _transferBinOrderRepository.UpdEntity(transobj);
            _transferBinOrderDetailRepository.UpdEntity(transDetailobj);

            //查询出移库的仓位
            var oldCell = _cellRepository.QueryEntityWhere(c=>c.Code == transDetailobj.FromLocationCode);
            if (oldCell == null)
            {
                message = "未查询到原仓位";
                return false;
            }
            var toCell = _cellRepository.QueryEntityWhere(c => c.Code == transDetailobj.ToLocationCode);
            if (toCell == null)
            {
                message = "未查询到目标仓位";
                return false;
            }

            //查询库存数据并将其修改回去
            var tinventorylist = _inventoryRepository.GetEntityWhereAll(it => it.LocationCode == toCell.Code && it.Status == 2).ToList();
            if (!tinventorylist.Any())
            {
                message = "库存不存在";
                return false;
            }
            var pallobj = _palletRepository.QueryEntityWhere(x => x.LocationCode == toCell.Code);
            if (pallobj == null)
            {
                message = "未查询到仓位所在托盘!";
                return false;
            }
            pallobj.LocationName = oldCell.Name;
            pallobj.LocationCode = oldCell.Code;
            _palletRepository.UpdEntity(pallobj);
            foreach (var inventory in tinventorylist)
            {
                inventory.LocationId = oldCell.Id;
                inventory.LocationName = oldCell.Name;
                inventory.LocationCode = oldCell.Code;
                inventory.LocationDepth = oldCell.DepthIndex;
                inventory.LocationLineNo = oldCell.LineNo;
                inventory.LocationLayerNo = oldCell.LayerNo;
                inventory.LocationColumnNo = oldCell.ColumnNo;
                inventory.Status = 1;
                inventory.LocationHeightType = oldCell.HeightType;
                inventory.IsLock = false;
                inventory.RoutewayId = oldCell.RoutewayId;
                inventory.ErplocationCode = oldCell.Erpcode;
                if (inventory.RelatedOrderDetailId == null)
                {
                    message = "关联的入库单id有误！";
                    return false;
                }
                //更新入库单的仓位信息
                var revingobj = _receivingOrderDetailRepository.QueryEntityById((long)inventory.RelatedOrderDetailId);
                if (revingobj == null)
                {
                    message = "入库单明细不存在或已被删除";
                    return false;
                }
                else
                {
                    revingobj.LocationId = oldCell.Id;
                    revingobj.LocationCode = oldCell.Code;
                    revingobj.LocationName = oldCell.Name;
                    revingobj.ModifyDate = DateTime.Now;
                    _receivingOrderDetailRepository.UpdEntity(revingobj);
                }

                var putawayOrder = _putawayOrderRepository.QueryEntityWhere(p => p.PalletBarcode == pallobj.PalletBarcode && p.Status == 4 && p.SourceType == 3);
                if (putawayOrder == null)
                {
                    message = "未查询到移库任务单";
                    return false;
                }
                if (!string.IsNullOrEmpty(putawayOrder.SiteCode))
                {
                    pickingCode = putawayOrder.Code;
                }
                _putawayOrderRepository.DelEntity(putawayOrder);
                if (!_unitOfWork.SaveChangesEntity())
                {
                    message = "取消任务失败!";
                    return false;
                }
            }
            if (pickingCode == null)
            {
                message = "未获取到任务号";
                return false;
            }
            CancelTaskData cancelTaskData = new CancelTaskData();
            cancelTaskData.MsgTime = DateTime.Now.ToString();
            cancelTaskData.TaskId = pickingCode;
            if (Config.IsDev == false)
            {
                var newWcsApi = wcsHttpClient.CancelTaskApi(cancelTaskData);
                if (newWcsApi.returnStatus == 1)
                {
                    message = "取消任务失败," + newWcsApi.returnInfo;
                    return false;
                }
            }
            //查询指令并删除掉
            var instructlist = _instructRepository.GetEntityWhereAll(i => i.RelatedOrderId == transobj.Id).ToList();
            if (instructlist.Count() <= 0)
            {
                message = "查询指令失败!";
                return false;
            }
            _instructRepository.DelEntityList(instructlist);

            return _unitOfWork.SaveChangesEntity();

        }
        #endregion
        public List<Instruct> GetInstructList(int InstructType, int Status, string? PalletBarcode, int pageIndex, int pageSize, out int totalCount)
        {
            var instructlist = _instructRepository.GetEntityAlls();
            // 添加条件判断
            if (InstructType != 0)
            {
                instructlist = instructlist.Where(t => t.InstructType == InstructType);
            }

            if (Status != 0)
            {
                instructlist = instructlist.Where(t => t.Status == Status);
            }

            if (!string.IsNullOrEmpty(PalletBarcode))
            {
                instructlist = instructlist.Where(t => t.PalletBarcode.Contains(PalletBarcode));
            }
            var list = _instructRepository.GetEntityAlls(instructlist, pageIndex, pageSize, out totalCount, x => x.CreateDate, false);
            return list.ToList();
        }

        public List<InstructMaterDto> GetInstructMater(long id)
        {
            List<InstructMaterDto> instructMaterDtolist = new List<InstructMaterDto>();
            var tinstructobj = _instructRepository.QueryEntityById(id);
            if (tinstructobj == null)
            {
                return instructMaterDtolist;
            }
            var receiobj = _receivingOrderDetailRepository.QueryEntityById((long)tinstructobj.RelatedOrderId);
            var shipplockobj = _shippingLockCellRepository.QueryIsEntityWhere(x => x.OrderDetailId == tinstructobj.RelatedOrderId);
            var transobj = _transferBinOrderDetailRepository.QueryIsEntityWhere(t=>t.Id == tinstructobj.RelatedOrderDetailId);
            InstructMaterDto instructmaterdtoobj = new InstructMaterDto();
            switch (tinstructobj.InstructType)
            {
                case 1:
                    if (receiobj != null)
                    {
                        instructmaterdtoobj.MaterName = receiobj.MaterialName;
                        instructmaterdtoobj.MaterNum = tinstructobj.Qty;
                        instructMaterDtolist.Add(instructmaterdtoobj);
                    }
                    break;
                case 2:
                    if (shipplockobj != null)
                    {
                        instructmaterdtoobj.MaterName = shipplockobj.MaterialName;
                        instructmaterdtoobj.MaterNum = tinstructobj.Qty;
                        instructMaterDtolist.Add(instructmaterdtoobj);
                    }
                    break;
                case 3:
                    if (transobj != null)
                    {
                        instructmaterdtoobj.MaterName = transobj.MaterialName;
                        instructmaterdtoobj.MaterNum = tinstructobj.Qty;
                        instructMaterDtolist.Add(instructmaterdtoobj);
                    }
                    break;
                case 6:
                    if (shipplockobj != null)
                    {
                        instructmaterdtoobj.MaterName = shipplockobj.MaterialName;
                        instructmaterdtoobj.MaterNum = tinstructobj.Qty;
                        instructMaterDtolist.Add(instructmaterdtoobj);
                    }
                    break;
                case 7:
                    if (receiobj != null)
                    {
                        instructmaterdtoobj.MaterName = receiobj.MaterialName;
                        instructmaterdtoobj.MaterNum = tinstructobj.Qty;
                        instructMaterDtolist.Add(instructmaterdtoobj);
                    }
                    break;
            }
            return instructMaterDtolist;
        }


        /// <summary>
        /// 修改目标位置
        /// </summary>
        /// <param name="taskChange"></param>
        /// <returns></returns>
        public bool WmsTaskChangeApi(TaskChangeDTO taskChangeDTO, out string message)
        {
            message = string.Empty;
            string TaskCode = null;
            bool result = false;
            var pallet = _palletRepository.QueryEntityWhere(P => P.Status == 1 && P.PalletBarcode == taskChangeDTO.PalletCode);
            if (pallet == null) 
            {
                message = "未查询到托盘信息";
                return false;
            }
            //查询托盘的上架指令
            var putawayOrderList = _putawayOrderRepository.GetEntityWhereAll(p => p.PalletBarcode == taskChangeDTO.PalletCode && p.Status == 4 && p.SourceType == 1).ToList();
            if (putawayOrderList.Count() <= 0)
            {
                message = "没查询到上架单!";
                return false;
            }
            _unitOfWork.BeginTransaction();
            try
            {
                foreach (var putawayOrder in putawayOrderList)
                {
                    if (putawayOrder.SiteCode != null)
                    {
                        TaskCode = putawayOrder.Code;//一个托盘多个指令,只会有一个SiteCode不会空,不为空的则是给WCS下发的任务数据
                    }
                    if (putawayOrder == null)
                    {
                        message = "未查询到托盘的上架任务!";
                        _unitOfWork.RollbackChanges();
                        return false;
                    }
                    if (taskChangeDTO.IsLockCell)
                    {
                        var oldCell = _cellRepository.QueryEntityWhere(c => c.Code == putawayOrder.LocationCode);
                        if (oldCell == null)
                        {
                            message = "未查询到原储位";
                            _unitOfWork.RollbackChanges();
                            return false;
                        }
                        //修改原来储位为正常
                        oldCell.Status = 1;
                        oldCell.IsLock = false;
                        oldCell.BusinessType = 0;
                        oldCell.FullStatus = 0;
                        _cellRepository.UpdEntity(oldCell);
                    }
                    var cellData = _cellRepository.QueryEntityWhere(c => c.Code == taskChangeDTO.UpdateCellCode && c.Status == 1 && c.IsLock == false);
                    if (cellData == null)
                    {
                        message = "未查询到更换的仓位!";
                        _unitOfWork.RollbackChanges();
                        return false;
                    }
                    //修改目标仓位
                    cellData.Status = 2;
                    cellData.IsLock = true;
                    cellData.BusinessType = 1;
                    cellData.FullStatus = 1;
                    _cellRepository.UpdEntity(cellData);

                    var receivingOrder = _receivingOrderDetailRepository.QueryEntityWhere(r => r.Id == putawayOrder.RelatedOrderDetailId && r.Status == 2);
                    if (receivingOrder == null)
                    {
                        message = "未查询到入库单!";
                        _unitOfWork.RollbackChanges();
                        return false;
                    }

                    var stackingStorage = _stackingStorageRepository.QueryEntityWhere(s => s.Id == putawayOrder.StackingStorageId);
                    if (stackingStorage == null)
                    {
                        message = "未查询到组垛数据!";
                        _unitOfWork.RollbackChanges();
                        return false;
                    }

                    var instruct = _instructRepository.QueryEntityWhere(i => i.RelatedOrderId == receivingOrder.Id && i.Status == 2);
                    if (instruct == null)
                    {
                        message = "未查询到入库指令!";
                        _unitOfWork.RollbackChanges();
                        return false;
                    }

                    var inventoryData = _inventoryRepository.QueryEntityWhere(i => i.RelatedOrderDetailId == receivingOrder.Id && i.Status == 3);
                    if (inventoryData == null)
                    {
                        message = "未查询到库存数据!";
                        _unitOfWork.RollbackChanges();
                        return false;
                    }

                    //修改上架单
                    putawayOrder.LocationCode = cellData.Code;
                    putawayOrder.LocationDepth = cellData.DepthIndex;

                    _putawayOrderRepository.UpdEntity(putawayOrder);
                    //修改入库单
                    receivingOrder.LocationId = cellData.Id;
                    receivingOrder.LocationName = cellData.Name;
                    receivingOrder.LocationCode = cellData.Code;
                    _receivingOrderDetailRepository.UpdEntity(receivingOrder);
                    //修改库存
                    inventoryData.LocationDepth = cellData.DepthIndex;
                    inventoryData.WarehouseId = cellData.WhId;
                    inventoryData.WarehouseCode = cellData.WhCode;
                    inventoryData.WarehouseName = cellData.WhName;
                    inventoryData.AreaCode = cellData.AreaCode;
                    inventoryData.AreaName = cellData.AreaName;
                    inventoryData.AreaId = cellData.AreaId;
                    inventoryData.LocationId = cellData.Id;
                    inventoryData.LocationCode = cellData.Code;
                    inventoryData.LocationDepth = cellData.DepthIndex;
                    inventoryData.LocationName = cellData.Name;
                    inventoryData.ErplocationCode = cellData.Erpcode;
                    inventoryData.RoutewayId = cellData.RoutewayId;
                    inventoryData.LocationHeightType = cellData.HeightType;
                    inventoryData.LocationColumnNo = cellData.ColumnNo;
                    inventoryData.LocationLayerNo = cellData.LayerNo;
                    inventoryData.LocationDistanceValue = cellData.DistanceValue;
                    inventoryData.LocationLineNo = cellData.LineNo;
                    _inventoryRepository.UpdEntity(inventoryData);
                    //修改组垛表
                    stackingStorage.ExpectedLocation = cellData.Code;
                    stackingStorage.ActualLocation = cellData.Code;
                    _stackingStorageRepository.UpdEntity(stackingStorage);
                    //修改指令
                    instruct.ExpectedToLocation = cellData.Code;
                    instruct.ToLocation = cellData.Code;
                    _instructRepository.UpdEntity(instruct);

                    result = _unitOfWork.SaveChangesEntity();
                }
                if (TaskCode == null)
                {
                    message = "未获取到任务号";
                    _unitOfWork.RollbackChanges();
                    return false;
                }
                TaskChange taskChange = new TaskChange
                {
                    TaskId = TaskCode,
                    EndNode = taskChangeDTO.UpdateCellCode,
                    MsgTime = DateTime.Now.ToString()
                };
                if (Config.IsDev == false)
                {
                    var wcsApiRes = wcsHttpClient.WMSUpdateTask(taskChange);
                    if (wcsApiRes.returnStatus == 1)
                    {
                        message = wcsApiRes.returnInfo;
                        _unitOfWork.RollbackChanges();
                        return false;
                    }
                }
                if (!result)
                {
                    message = "修改失败!";
                    _unitOfWork.RollbackChanges();
                    return false;
                }
                message = "修改成功!";
                _unitOfWork.CommitChanges();
                return true;
            }
            catch (Exception ex)
            {
                message = "修改失败!" + ex.Message;
                _unitOfWork.CommitChanges();
                return false;
            }
        }


        #region 取消出库产生移库逻辑处理
        private Cell? ShippingTransferBinInventory(int layerno, string trancellcode, string acode, out string message)
        {
            message = string.Empty;
            #region 修改库存状态
            var toCell = GetCellCode(acode, layerno, out message);
            if (toCell == null)
            {
                message = "当前层没有可移库的仓位了！";
                return null;
            }
            else
            {
                toCell.FullStatus = 1;
                toCell.IsLock = true;
                toCell.BusinessType = 1;
                toCell.ModifyDate = DateTime.Now;
                _cellRepository.UpdEntity(toCell);
            }
            bool isshipplost = false;
            var slocklist = _shippingLockCellRepository.GetEntityWhereAll(x => x.CellCode == trancellcode && x.Status == 0).ToList();
            foreach (var item2 in slocklist)
            {
                //标记状态列
                item2.CellId = toCell.Id;
                item2.CellCode = toCell.Code;
                item2.CellName = toCell.Name;
                item2.Status = 3;
                isshipplost = true;
                _shippingLockCellRepository.UpdEntity(item2);
            }
            var tinventorylist = _inventoryRepository.GetEntityWhereAll(it => it.LocationCode == trancellcode).ToList();
            foreach (var inventory in tinventorylist)
            {
                inventory.LocationId = toCell.Id;
                inventory.LocationName = toCell.Name;
                inventory.LocationCode = toCell.Code;
                inventory.LocationDepth = toCell.DepthIndex;
                inventory.LocationLineNo = toCell.LineNo;
                inventory.LocationLayerNo = toCell.LayerNo;
                inventory.LocationColumnNo = toCell.ColumnNo;
                inventory.Status = 2;
                inventory.LocationHeightType = toCell.HeightType;
                inventory.IsLock = true;
                inventory.RoutewayId = toCell.RoutewayId;
                inventory.ErplocationCode = toCell.Erpcode;
                if (isshipplost)
                    inventory.Remark = "系统移库";
                _inventoryRepository.UpdEntity(inventory);
                #region 关联的入库单做处理
                if (inventory.RelatedOrderDetailId == null)
                {
                    message = "关联的入库单id有误！";
                    return null;
                }
                var revingobj = _receivingOrderDetailRepository.QueryEntityById((long)inventory.RelatedOrderDetailId);
                if (revingobj == null)
                {
                    message = "入库单明细不存在或已被删除";
                    return null;
                }
                #region 指令管理
                Instruct instruct = null;
                instruct = new Instruct
                {
                    Id = YitIdHelper.NextId(),
                    WarehouseCode = toCell.WhCode,
                    Status = 2,
                    FromLocation = trancellcode,
                    ToLocation = toCell.Code,
                    StackingStorageId = 0,
                    WorkDeviceType = 1,
                    InstructType = 3,
                    Action = 0,
                    RelatedOrderId = revingobj.Id,
                    RelatedOrderDetailId = 0,
                    DeviceCode = "",
                    ExpectedToLocation = toCell.Code,
                    InstructIndex = 1,
                    PalletBarcode = inventory.PalletBarcode,
                    ScanedBarcode = inventory.PalletBarcode,
                    Priority = 9999,
                    Qty = inventory.AvailableQty == null ? 0 : (decimal)inventory.AvailableQty,
                    FinishedQty = 0,
                    CreateDate = DateTime.Now,
                    BusinessType = (int)EmBusinessType.Move,
                    BillType = (int)revingobj.BillType.GetValueOrDefault(),
                };
                _instructRepository.AddEntity(instruct);
                #endregion
                #endregion


                #endregion
                #region 上架单
                string tstr = DateTime.Now.ToString("yyyyMMddHHmmssfff");
                string traawayCode = "TRA" + tstr;
                PutawayOrder putawayOrder = new PutawayOrder();
                putawayOrder.Id = YitIdHelper.NextId();
                putawayOrder.Code = traawayCode;
                putawayOrder.RelatedOrderDetailId = tinventorylist.First().RelatedOrderDetailId;
                putawayOrder.StackingStorageId = 0;
                putawayOrder.PalletBarcode = tinventorylist.First().PalletBarcode;
                putawayOrder.LocationCode = toCell.Code;
                putawayOrder.LocationDepth = toCell.DepthIndex == 0 ? null : toCell.DepthIndex;
                putawayOrder.Status = 4;
                putawayOrder.Qty = tinventorylist.First().AvailableQty;
                putawayOrder.CreateDate = DateTime.Now;
                putawayOrder.MaterialId = tinventorylist.First().MaterialId;
                putawayOrder.MaterialCode = tinventorylist.First().MaterialCode;
                putawayOrder.MaterialName = tinventorylist.First().MaterialName;
                putawayOrder.MaterialKeyId = tinventorylist.First().MaterialKeyId;
                putawayOrder.BatchNo = tinventorylist.First().BatchNo;
                putawayOrder.CreateUserId = 0;
                putawayOrder.CreateUserName = "系统";
                putawayOrder.SourceType = 3;
                putawayOrder.SiteCode = "";
                _putawayOrderRepository.AddEntity(putawayOrder);
            }
            var pallobj = _palletRepository.QueryEntityWhere(x => x.LocationCode == trancellcode);
            if (pallobj != null)
            {
                pallobj.LocationName = toCell.Name;
                pallobj.LocationCode = toCell.Code;
            }

            #endregion
            if (!_unitOfWork.SaveChangesEntity())
            {
                message = "修改数据失败";
                return null;
            }

            return toCell;
        }

        private Cell? GetCellCode(string acode, int layerno, out string message)
        {
            message = string.Empty;
            if (string.IsNullOrEmpty(acode))
            {
                message = "库区编码有误！";
                return null;
            }
            Cell? cellobj = new Cell();
            //获取所有库区
            var areaobj = _areaRepository.QueryIsEntityWhere(x => x.Code == acode && x.Status == 1);
            if (areaobj == null || areaobj.WhId == null)
            {
                message = "库区不存在或已被禁用!";
                return null;
            }
            long? wid = areaobj.WhId;
            //获取所有库房
            var warehouseobj = _warehouseRepository.QueryIsEntityWhere(x => x.Id == wid && x.Status == 1);
            if (warehouseobj == null)
            {
                message = "库房不存在或已被禁用!";
                return null;
            }

            //获取所有巷道
            var routewayQuery = _routewayRepository.GetEntityWhereAll(x => x.WhId == wid && x.Status == 1);
            if (routewayQuery == null)
            {
                message = "无可用巷道!";
                return null;
            }
            List<long> enabledRoutewayIds = routewayQuery.Select(t => t.Id).ToList();//只取巷道id
            // 获取所有货架
            var shelves = _shelfRepository.GetEntityWhereAll(x => x.WhId == wid && x.AreaId == areaobj.Id && x.Status == 1 && enabledRoutewayIds.Contains((long)x.RoutewayId));
            if (shelves == null)
            {
                message = "无可用货架!";
                return null;
            }
            List<long> enabledShelves = shelves.Select(t => t.Id).ToList();//只取货架id
            //获取所有可用仓位
            var cellQuery = _cellRepository
                .GetEntityWhereAll(x => x.AreaCode == acode
                                        && x.Status == 1
                                        && x.FullStatus == 0
                                        && x.IsLock == false
                                        && x.LayerNo == layerno
                                        && enabledRoutewayIds.Contains((long)x.RoutewayId)
                                        && enabledShelves.Contains((long)x.ShelfId)).ToList();
            if (!cellQuery.Any())
            {
                message = "无可用仓位!";
                return null;
            }
            //var inventoryQuery = Context.TInventory.AsNoTracking(); //获取库存数据
            cellobj = cellQuery.Where(x => x.IsMaxDepth == true).OrderByDescending(c => c.DepthIndex)
                                .ThenBy(c => c.LayerNo)
                                .ThenBy(c => c.ColumnNo)
                                .ThenBy(c => c.LineNo)
                                .FirstOrDefault();
            if (cellobj != null)
            {
                return cellobj;
            }
            else
            {
                cellobj = cellQuery.Where(x => x.IsMaxDepth == false).OrderByDescending(c => c.DepthIndex)
                              .ThenBy(c => c.LayerNo)
                              .ThenBy(c => c.ColumnNo)
                              .ThenBy(c => c.LineNo)
                              .FirstOrDefault();
                if (cellobj != null)
                {
                    return cellobj;
                }
            }
            if (cellobj == null)
                message = "无可用仓位!";
            return null;
        }
        #endregion
    }
}
